/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include <stdio.h>
#include <string.h>
#include <math.h>

#include <flgrCoreData.h>
#include <flgrCoreIO.h>
#include <flgrCoreDispatch.h>
#include <flgrCoreCompare.h>
#include <flgrCoreReplace.h>
#include <flgrCoreCopy.h>
#include <flgrCoreSlideWindow.h>
#include <flgrMeasureBase.h>
#include <flgrArith.h>
#include "flgrMorphoKerOp.h"
#include "flgrMorphoSkiz.h"
#include "flgrMorphoSkizFast.h"
#include "flgrMorphoLabel.h"
#include "../image/flgrImageIO.h"


void flgr2d_dilate_preserving_skiz_fgBIT(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr_no_define_type_function(FLGR_BIT);  
}

void flgr2d_dilate_preserving_skiz_fgUINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;

#if  defined(__SSE2__) || (defined(__SSE__) && defined(__MMX__))
  if((nhb->shape==FLGR_RECT) && (nhb->connexity==FLGR_8_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_8_connex_fgUINT8(datdest,datsrc);
      
  }else if((nhb->shape==FLGR_CROSS) && (nhb->connexity==FLGR_4_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_4_connex_fgUINT8(datdest,datsrc);
      
  }else if((nhb->shape==FLGR_HEX) && (nhb->connexity==FLGR_6_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_6_connex_fgUINT8(datdest,datsrc);
      
  }else {
    flgr2d_raster_slide_window_fgUINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgUINT8);
  }

#else

  flgr2d_raster_slide_window_fgUINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgUINT8);

#endif
}

void flgr2d_dilate_preserving_skiz_fgUINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;

#if  defined(__SSE2__) || (defined(__SSE__) && defined(__MMX__))

  if((nhb->shape==FLGR_RECT) && (nhb->connexity==FLGR_8_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_8_connex_fgUINT16(datdest,datsrc);

  }else if((nhb->shape==FLGR_CROSS) && (nhb->connexity==FLGR_4_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_4_connex_fgUINT16(datdest,datsrc);

  }else if((nhb->shape==FLGR_HEX) && (nhb->connexity==FLGR_6_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_6_connex_fgUINT16(datdest,datsrc);

  }else {
    flgr2d_raster_slide_window_fgUINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgUINT16);
  }
#else

  flgr2d_raster_slide_window_fgUINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgUINT16);

#endif
}

void flgr2d_dilate_preserving_skiz_fgUINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  if((nhb->shape==FLGR_RECT) && (nhb->connexity==FLGR_8_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_8_connex_fgUINT32(datdest,datsrc);
  }else {
    flgr2d_raster_slide_window_fgUINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgUINT32);
  }
}

void flgr2d_dilate_preserving_skiz_fgINT8(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  if((nhb->shape==FLGR_RECT) && (nhb->connexity==FLGR_8_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_8_connex_fgINT8(datdest,datsrc);
  }else {
    flgr2d_raster_slide_window_fgINT8(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgINT8);
  }
}

void flgr2d_dilate_preserving_skiz_fgINT16(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  if((nhb->shape==FLGR_RECT) && (nhb->connexity==FLGR_8_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_8_connex_fgINT16(datdest,datsrc);
  }else {
    flgr2d_raster_slide_window_fgINT16(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgINT16);
  }
}

void flgr2d_dilate_preserving_skiz_fgINT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  if((nhb->shape==FLGR_RECT) && (nhb->connexity==FLGR_8_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_8_connex_fgINT32(datdest,datsrc);
  }else {
    flgr2d_raster_slide_window_fgINT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgINT32);
  }
}

void flgr2d_dilate_preserving_skiz_fgFLOAT32(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  if((nhb->shape==FLGR_RECT) && (nhb->connexity==FLGR_8_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_8_connex_fgFLOAT32(datdest,datsrc);
  }else {
    flgr2d_raster_slide_window_fgFLOAT32(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgFLOAT32);
  }
}

void flgr2d_dilate_preserving_skiz_fgFLOAT64(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  if((nhb->shape==FLGR_RECT) && (nhb->connexity==FLGR_8_CONNEX) && (nhb->size_x==3) && (nhb->size_y==3)) {
    flgr2d_dilate_preserving_skiz_fast_8_connex_fgFLOAT64(datdest,datsrc);
  }else {
    flgr2d_raster_slide_window_fgFLOAT64(datdest, datsrc, nhb, FLGR_NHB_NO_SYM, flgr2d_get_nhb_max_keep_skiz_fgFLOAT64);
  }
}



////////////////////////////////////////////////////////////////////////////
/*! Dilate a label image and avoid mix of different labels
 *  @param *datdest : pointer to the image
 *  @param *datsrc : pointer to the image
 *  @param *nhb : pointer the the 2D Neighborhood definition
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_dilate_preserving_skiz(FLGR_Data2D *datdest, FLGR_Data2D *datsrc, FLGR_Data2D *nhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;
  if((datdest==NULL) || (datsrc==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret=flgr2d_is_data_same_attributes(datdest,datsrc,__FUNCTION__))!=FLGR_RET_OK) return ret;
  if((ret=flgr2d_is_data_same_type(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("data types differents\n");
    return ret;
  }

  if((ret=flgr2d_is_data_same_spp(datdest,nhb))!=FLGR_RET_OK) {
    POST_ERROR("spp differents\n");
    return ret;
  }

  FLGR_DISPATCH_PROCEDURE(datdest->type,flgr2d_dilate_preserving_skiz,datdest,datsrc,nhb);

}





#define FLGR2D_MACRO_SKIZ(dtype)					\
  FLGR_Data2D *tmp;							\
  									\
  tmp = flgr2d_create_##dtype(labelizedImage->size_y,			\
			      labelizedImage->size_x,			\
			      labelizedImage->spp,			\
			      FLGR_NO_SHAPE,				\
			      FLGR_NO_CONNEX);				\
									\
  do {									\
    flgr2d_copy_##dtype##_##dtype(tmp, labelizedImage);			\
    flgr2d_dilate_preserving_skiz(labelizedImage,tmp,nhb);		\
  }while(flgr2d_compare_##dtype(tmp,FLGR_TEST_EQ,labelizedImage)	\
	 !=FLGR_TRUE);							\
									\
  flgr2d_destroy(tmp);

void flgr2d_skiz_fgBIT(FLGR_Data2D *labelizedImage, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr_no_define_type_function(FLGR_BIT);  
}
void flgr2d_skiz_fgUINT8(FLGR_Data2D *labelizedImage, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_SKIZ(fgUINT8);
}
void flgr2d_skiz_fgUINT16(FLGR_Data2D *labelizedImage, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_SKIZ(fgUINT16);
}
void flgr2d_skiz_fgUINT32(FLGR_Data2D *labelizedImage, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_SKIZ(fgUINT32);
}
void flgr2d_skiz_fgINT8(FLGR_Data2D *labelizedImage, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_SKIZ(fgINT8);
}
void flgr2d_skiz_fgINT16(FLGR_Data2D *labelizedImage, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_SKIZ(fgINT16);
}
void flgr2d_skiz_fgINT32(FLGR_Data2D *labelizedImage, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_SKIZ(fgINT32);
}
void flgr2d_skiz_fgFLOAT32(FLGR_Data2D *labelizedImage, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_SKIZ(fgFLOAT32);
}
void flgr2d_skiz_fgFLOAT64(FLGR_Data2D *labelizedImage, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_SKIZ(fgFLOAT64);
}




////////////////////////////////////////////////////////////////////////////
/*! Compute Skiz
 *  @param *datdest : return labelized influence region
 *  @param *datsrc : pointer to the image
 *  @param connexity : connexity
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_skiz(FLGR_Data2D *labelizedImage, FLGR_Connexity connexity) {
  FLGR_Ret ret;
  FLGR_Data2D *nhb;

  FLGR_DECLARE_FUNCTION;
  if(labelizedImage==NULL) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }


  nhb = flgr2d_create_neighborhood_from_connexity(labelizedImage->spp,labelizedImage->type,connexity);
  if(nhb==NULL) return FLGR_RET_ALLOCATION_ERROR;

  

  switch(labelizedImage->type) {
  case FLGR_UINT8:
    flgr2d_skiz_fgUINT8(labelizedImage,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_UINT16:
    flgr2d_skiz_fgUINT16(labelizedImage,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_UINT32:
    flgr2d_skiz_fgUINT32(labelizedImage,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_INT8:
    flgr2d_skiz_fgINT8(labelizedImage,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_INT16:
    flgr2d_skiz_fgINT16(labelizedImage,nhb);
    ret = FLGR_RET_OK;break;
 
  case FLGR_INT32:
    flgr2d_skiz_fgINT32(labelizedImage,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_FLOAT32:
    flgr2d_skiz_fgFLOAT32(labelizedImage,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_FLOAT64:
    flgr2d_skiz_fgFLOAT64(labelizedImage,nhb);
    ret = FLGR_RET_OK;break;
    
  default:
    ret = FLGR_RET_PARAM_ERROR;break;
  }


  flgr2d_destroy(nhb);

  return ret;
}
















#define FLGR2D_MACRO_GEODESIC_SKIZ(dtype)				\
  FLGR_Data2D *tmp;							\
  tmp = flgr2d_create_##dtype(datmask->size_y, datmask->size_x,		\
			      datmask->spp,				\
			      FLGR_NO_SHAPE,				\
			      FLGR_NO_CONNEX);				\
  do {									\
    flgr2d_copy_##dtype##_##dtype(tmp, labelizedImage);			\
    flgr2d_dilate_preserving_skiz(labelizedImage,tmp,nhb);		\
    flgr2d_arith_inf(labelizedImage, labelizedImage, datmask);		\
  }while(flgr2d_compare_##dtype(tmp,FLGR_TEST_EQ,labelizedImage)	\
	 !=FLGR_TRUE);							\
  									\
  flgr2d_destroy(tmp);

void flgr2d_geodesic_skiz_fgBIT(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  flgr_no_define_type_function(FLGR_BIT);  
}
void flgr2d_geodesic_skiz_fgUINT8(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_GEODESIC_SKIZ(fgUINT8);
}
void flgr2d_geodesic_skiz_fgUINT16(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_GEODESIC_SKIZ(fgUINT16);
}
void flgr2d_geodesic_skiz_fgUINT32(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_GEODESIC_SKIZ(fgUINT32);
}
void flgr2d_geodesic_skiz_fgINT8(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_GEODESIC_SKIZ(fgINT8);
}
void flgr2d_geodesic_skiz_fgINT16(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_GEODESIC_SKIZ(fgINT16);
}
void flgr2d_geodesic_skiz_fgINT32(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_GEODESIC_SKIZ(fgINT32);
}
void flgr2d_geodesic_skiz_fgFLOAT32(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_GEODESIC_SKIZ(fgFLOAT32);
}
void flgr2d_geodesic_skiz_fgFLOAT64(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;
  FLGR2D_MACRO_GEODESIC_SKIZ(fgFLOAT64);
}




////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Skiz
 *  @param *datdest : return labelized influence region
 *  @param *datmask : pointer to the image
 *  @param *datsrc : pointer to the image
 *  @param connexity : connexity
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_skiz(FLGR_Data2D *labelizedImage, FLGR_Data2D *datmask, FLGR_Connexity connexity) {
  FLGR_Ret ret;
  FLGR_Data2D *nhb;

  FLGR_DECLARE_FUNCTION;
  if((labelizedImage==NULL) || (datmask==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret=flgr2d_is_data_same_attributes(labelizedImage,datmask,__FUNCTION__))!=FLGR_RET_OK) return ret;
 

  nhb = flgr2d_create_neighborhood_from_connexity(datmask->spp,datmask->type,connexity);
  if(nhb==NULL) return FLGR_RET_ALLOCATION_ERROR;

  

  switch(labelizedImage->type) {
  case FLGR_UINT8:
    flgr2d_geodesic_skiz_fgUINT8(labelizedImage,datmask,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_UINT16:
    flgr2d_geodesic_skiz_fgUINT16(labelizedImage,datmask,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_UINT32:
    flgr2d_geodesic_skiz_fgUINT32(labelizedImage,datmask,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_INT8:
    flgr2d_geodesic_skiz_fgINT8(labelizedImage,datmask,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_INT16:
    flgr2d_geodesic_skiz_fgINT16(labelizedImage,datmask,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_INT32:
    flgr2d_geodesic_skiz_fgINT32(labelizedImage,datmask,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_FLOAT32:
    flgr2d_geodesic_skiz_fgFLOAT32(labelizedImage,datmask,nhb);
    ret = FLGR_RET_OK;break;

  case FLGR_FLOAT64:
    flgr2d_geodesic_skiz_fgFLOAT64(labelizedImage,datmask,nhb);
    ret = FLGR_RET_OK;break;

  default:
    ret = FLGR_RET_TYPE_UNKNOWN;break;
  }


  flgr2d_destroy(nhb);

  return ret;
}














#define FLGR2D_MACRO_WATERSHED_BY_GEODESIC_SKIZ(dtype)			\
  FLGR_Data2D *nhb,*tmp,*mask;						\
  FLGR_Vector *mini, *maxi, *current, *vectrue, *vecfalse;		\
  dtype valmin,valmax,m;						\
  dtype itrue = MAX_##dtype;						\
  dtype ifalse = MIN_##dtype;						\
  int i;								\
									\
									\
  nhb = flgr2d_create_neighborhood_from_connexity(datsrc->spp,		\
						  datsrc->type,		\
						  connexity);		\
  									\
  tmp = flgr2d_create_##dtype(datsrc->size_y, datsrc->size_x,		\
			      datsrc->spp,				\
			      FLGR_NO_SHAPE,				\
			      FLGR_NO_CONNEX);				\
									\
  mask = flgr2d_create_##dtype(datsrc->size_y, datsrc->size_x,		\
			       datsrc->spp,				\
			       FLGR_NO_SHAPE,				\
			       FLGR_NO_CONNEX);				\
  									\
  mini = flgr_vector_create(datsrc->spp,datsrc->type);			\
  maxi = flgr_vector_create(datsrc->spp,datsrc->type);			\
  current = flgr_vector_create(datsrc->spp,datsrc->type);		\
  vectrue = flgr_vector_create(datsrc->spp,datsrc->type);		\
  vecfalse = flgr_vector_create(datsrc->spp,datsrc->type);		\
  									\
  flgr_vector_populate_from_scalar(vectrue,&itrue);			\
  flgr_vector_populate_from_scalar(vecfalse,&ifalse);			\
  									\
  flgr2d_measure_min_max_##dtype(datsrc, mini, maxi);			\
  									\
  flgr_vector_get_element(mini,0,&valmin);				\
  flgr_vector_get_element(maxi,0,&valmax);				\
  									\
  for(i=((int) valmin) ; i<=((int) valmax) ; i++) {			\
    m = (dtype) i;							\
    flgr_vector_populate_from_scalar(current,&m);			\
    flgr2d_replace_I_with_C_C_C_##dtype(mask, datsrc, FLGR_TEST_INFEQ,	\
					current, vectrue, vecfalse);	\
    									\
    flgr2d_geodesic_skiz_##dtype(labelizedMinima,mask,nhb);		\
  }									\
									\
  flgr_vector_destroy(mini);						\
  flgr_vector_destroy(maxi);						\
  flgr_vector_destroy(current);						\
  flgr_vector_destroy(vectrue);						\
  flgr_vector_destroy(vecfalse);					\
									\
  flgr2d_destroy(nhb);							\
  flgr2d_destroy(mask);							\
  flgr2d_destroy(tmp);

void flgr2d_watershed_by_skiz_fgBIT(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_DECLARE_FUNCTION;
  flgr_no_define_type_function(FLGR_BIT);  
}
void flgr2d_watershed_by_skiz_fgUINT8(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_DECLARE_FUNCTION;  
  FLGR2D_MACRO_WATERSHED_BY_GEODESIC_SKIZ(fgUINT8);
}
void flgr2d_watershed_by_skiz_fgUINT16(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_DECLARE_FUNCTION;  
  FLGR2D_MACRO_WATERSHED_BY_GEODESIC_SKIZ(fgUINT16);
}
void flgr2d_watershed_by_skiz_fgUINT32(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_DECLARE_FUNCTION;  
  FLGR2D_MACRO_WATERSHED_BY_GEODESIC_SKIZ(fgUINT32);
}
void flgr2d_watershed_by_skiz_fgINT8(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_DECLARE_FUNCTION;  
  FLGR2D_MACRO_WATERSHED_BY_GEODESIC_SKIZ(fgINT8);
}
void flgr2d_watershed_by_skiz_fgINT16(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_DECLARE_FUNCTION;  
  FLGR2D_MACRO_WATERSHED_BY_GEODESIC_SKIZ(fgINT16);
}
void flgr2d_watershed_by_skiz_fgINT32(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_DECLARE_FUNCTION;  
  FLGR2D_MACRO_WATERSHED_BY_GEODESIC_SKIZ(fgINT32);
}
void flgr2d_watershed_by_skiz_fgFLOAT32(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_DECLARE_FUNCTION;  
  FLGR2D_MACRO_WATERSHED_BY_GEODESIC_SKIZ(fgFLOAT32);
}
void flgr2d_watershed_by_skiz_fgFLOAT64(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_DECLARE_FUNCTION;  
  FLGR2D_MACRO_WATERSHED_BY_GEODESIC_SKIZ(fgFLOAT64);
}


////////////////////////////////////////////////////////////////////////////
/*! Compute Watershed using Geodesic Skiz
 *  @param *datdest : labelized minima
 *  @param *datsrc : input image
 *  @param connexity : connexity
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_watershed_by_skiz(FLGR_Data2D *labelizedMinima, FLGR_Data2D *datsrc, FLGR_Connexity connexity) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;
  if((labelizedMinima==NULL) || (datsrc==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if((ret=flgr2d_is_data_same_attributes(labelizedMinima,datsrc,__FUNCTION__))!=FLGR_RET_OK) return ret;

  if(labelizedMinima->spp != 1) {
    POST_ERROR("You can use only scalar pixels\n");
    return FLGR_RET_VECTOR_SIZE_ERROR;
  }

  FLGR_DISPATCH_PROCEDURE(labelizedMinima->type,flgr2d_watershed_by_skiz,labelizedMinima,datsrc,connexity);

}
